import sqlMapper from '@platformatic/sql-mapper'
import fastify from 'fastify'
import { equal, ok as pass, deepEqual as same } from 'node:assert'
import { test } from 'node:test'
import sqlGraphQL from '../index.js'
import { clear, connInfo, isPg } from './helper.js'

test('array support', { skip: !isPg }, async t => {
  const app = fastify()
  app.register(sqlMapper, {
    ...connInfo,
    async onDatabaseLoad (db, sql) {
      pass('onDatabaseLoad called')

      await clear(db, sql)
      await db.query(sql`CREATE TABLE pages (
      id SERIAL PRIMARY KEY,
      title VARCHAR(42) NOT NULL,
      tags VARCHAR(42)[] NOT NULL
    );`)
    }
  })
  app.register(sqlGraphQL)
  t.after(() => app.close())

  await app.ready()

  {
    const res = await app.inject({
      method: 'POST',
      url: '/graphql',
      body: {
        query: `
          mutation {
            savePage(input: { title: "Hello", tags: ["foo", "bar"] }) {
              id
              title
              tags
            }
          }
        `
      }
    })
    equal(res.statusCode, 200, 'savePage status code')
    same(
      res.json(),
      {
        data: {
          savePage: {
            id: 1,
            title: 'Hello',
            tags: ['foo', 'bar']
          }
        }
      },
      'savePage response'
    )
  }

  {
    const res = await app.inject({
      method: 'POST',
      url: '/graphql',
      body: {
        query: `
          query {
            getPageById(id: 1) {
              id
              title,
              tags
            }
          }
        `
      }
    })
    equal(res.statusCode, 200, 'pages status code')
    same(
      res.json(),
      {
        data: {
          getPageById: {
            id: 1,
            title: 'Hello',
            tags: ['foo', 'bar']
          }
        }
      },
      'pages response'
    )
  }

  {
    const res = await app.inject({
      method: 'POST',
      url: '/graphql',
      body: {
        query: `
          query {
            pages(where: { tags: { any: "foo" } }) {
              id
              title
              tags
            }
          }
        `
      }
    })
    equal(res.statusCode, 200, 'pages status code')
    same(
      res.json(),
      {
        data: {
          pages: [
            {
              id: 1,
              title: 'Hello',
              tags: ['foo', 'bar']
            }
          ]
        }
      },
      'pages response'
    )
  }

  {
    const res = await app.inject({
      method: 'POST',
      url: '/graphql',
      body: {
        query: `
          query {
            pages(where: { tags: { contains: ["foo"] } }) {
              id
              title
              tags
            }
          }
        `
      }
    })
    equal(res.statusCode, 200, 'pages status code')
    same(
      res.json(),
      {
        data: {
          pages: [
            {
              id: 1,
              title: 'Hello',
              tags: ['foo', 'bar']
            }
          ]
        }
      },
      'pages response'
    )
  }

  {
    const res = await app.inject({
      method: 'POST',
      url: '/graphql',
      body: {
        query: `
          query {
            pages(where: { tags: { contained: ["foo", "bar"] } }) {
              id
              title
              tags
            }
          }
        `
      }
    })
    equal(res.statusCode, 200, 'pages status code')
    same(
      res.json(),
      {
        data: {
          pages: [
            {
              id: 1,
              title: 'Hello',
              tags: ['foo', 'bar']
            }
          ]
        }
      },
      'pages response'
    )
  }

  {
    const res = await app.inject({
      method: 'POST',
      url: '/graphql',
      body: {
        query: `
          query {
            pages(where: { tags: { overlaps: ["foo"] } }) {
              id
              title
              tags
            }
          }
        `
      }
    })
    equal(res.statusCode, 200, 'pages status code')
    same(
      res.json(),
      {
        data: {
          pages: [
            {
              id: 1,
              title: 'Hello',
              tags: ['foo', 'bar']
            }
          ]
        }
      },
      'pages response'
    )
  }

  {
    const res = await app.inject({
      method: 'POST',
      url: '/graphql',
      body: {
        query: `
          query {
            pages(where: { tags: { any: "baz" } }) {
              id
              title,
              tags
            }
          }
        `
      }
    })
    equal(res.statusCode, 200, 'pages status code')
    same(
      res.json(),
      {
        data: {
          pages: []
        }
      },
      'pages response'
    )
  }

  {
    const res = await app.inject({
      method: 'POST',
      url: '/graphql',
      body: {
        query: `
          query {
            pages(where: { tags: { contains: ["baz"] } }) {
              id
              title,
              tags
            }
          }
        `
      }
    })
    equal(res.statusCode, 200, 'pages status code')
    same(
      res.json(),
      {
        data: {
          pages: []
        }
      },
      'pages response'
    )
  }

  {
    const res = await app.inject({
      method: 'POST',
      url: '/graphql',
      body: {
        query: `
          query {
            pages(where: { tags: { contained: ["foo"] } }) {
              id
              title,
              tags
            }
          }
        `
      }
    })
    equal(res.statusCode, 200, 'pages status code')
    same(
      res.json(),
      {
        data: {
          pages: []
        }
      },
      'pages response'
    )
  }

  {
    const res = await app.inject({
      method: 'POST',
      url: '/graphql',
      body: {
        query: `
          query {
            pages(where: { tags: { overlaps: ["baz"] } }) {
              id
              title,
              tags
            }
          }
        `
      }
    })
    equal(res.statusCode, 200, 'pages status code')
    same(
      res.json(),
      {
        data: {
          pages: []
        }
      },
      'pages response'
    )
  }

  {
    const res = await app.inject({
      method: 'POST',
      url: '/graphql',
      body: {
        query: `
          query {
            pages(where: { tags: { all: "foo" } }) {
              id
              title,
              tags
            }
          }
        `
      }
    })
    equal(res.statusCode, 200, 'pages status code')
    same(
      res.json(),
      {
        data: {
          pages: []
        }
      },
      'pages response'
    )
  }

  {
    const res = await app.inject({
      method: 'POST',
      url: '/graphql',
      body: {
        query: `
          mutation {
            savePage(input: { id: 1, title: "Hello World", tags: ["foo", "bar", "baz"] }) {
              id
              title
              tags
            }
          }
        `
      }
    })
    equal(res.statusCode, 200, 'savePage status code')
    same(
      res.json(),
      {
        data: {
          savePage: {
            id: 1,
            title: 'Hello World',
            tags: ['foo', 'bar', 'baz']
          }
        }
      },
      'savePage response'
    )
  }

  {
    const res = await app.inject({
      method: 'POST',
      url: '/graphql',
      body: {
        query: `
          query {
            getPageById(id: 1) {
              id
              title
              tags
            }
          }
        `
      }
    })
    equal(res.statusCode, 200, 'pages status code')
    same(
      res.json(),
      {
        data: {
          getPageById: {
            id: 1,
            title: 'Hello World',
            tags: ['foo', 'bar', 'baz']
          }
        }
      },
      'pages response'
    )
  }
})
